using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.IO;
using Budgetor.Properties;
using Microsoft.Win32;
using Budgetor.DataVizualization;
using Budgetor.Reports;

namespace Budgetor
{
    public partial class MainForm : Form
    {
        BudgetFile budgetFile;
        PieChartControl pcc = new PieChartControl();
        HistogramControl histogram = new HistogramControl();
        List<double> histogramdata = new List<double>();

        event EventHandler<DataEventArgs> dataUpdated;

        public MainForm()
        {
            InitializeComponent();
            pcc.Location = new Point(50,50);
            histogram.Location = new Point(50, 50);
            pcc.Size = new Size(757, 442);
            histogram.Size = new Size(757, 442);            

            dataUpdated += barGraphPanel1.UpdateData;
            dataUpdated += pieChartPanel1.UpdateData;
        }

        private void CalculateAmount()
        {
            Dictionary<string, float> amountTable = new Dictionary<string, float>();
            amountTable.Add(Resources.Cash, 0);
            amountTable.Add(Resources.TC, 0);
            amountTable.Add(Resources.WCC, 0);

            foreach (object obj in dataBindingSource)
            {
                Data dataItem = obj as Data;

                if (dataItem.Description == "Advance")
                    amountTable[dataItem.CurrencyMode] += dataItem.AmountReimbursed;
                else
                    amountTable[dataItem.CurrencyMode] -= dataItem.AmountSpent;
            }

            textBoxCashRemaining.Text = amountTable[Resources.Cash].ToString(Resources.DollarFormat);
            textBoxTCRemaining.Text = amountTable[Resources.TC].ToString(Resources.DollarFormat);
            textBoxWCCRemaining.Text = amountTable[Resources.WCC].ToString(Resources.DollarFormat);

            CalculateIncome();

            if (dataUpdated != null)
                dataUpdated(this, new DataEventArgs(dataBindingSource));
        }

        private void CalculateIncome()
        {
            float incomeDailyAllowance = 0;
            float incomeReimbursement = 0;
            float expenditures = 0;
            float total = 0;

            TimeSpan span = budgetFile.UseCurrentDateForAllowance ? DateTime.Today - budgetFile.AllowanceFrom
                : budgetFile.AllowanceTo - budgetFile.AllowanceFrom;
            int days = budgetFile.UseCurrentDateForAllowance ? span.Days + 2 : span.Days + 1;

            incomeDailyAllowance = days * budgetFile.DailyAllowance;

            foreach (object obj in dataBindingSource)
            {
                Data dataItem = obj as Data;
                if (dataItem.Description != "Advance")
                    incomeReimbursement += dataItem.AmountReimbursed;

                expenditures -= dataItem.AmountSpent;
            }

            total = incomeDailyAllowance + incomeReimbursement + expenditures;
            textBoxExpenditure.Text = expenditures.ToString(Resources.DollarFormat);
            textBoxReimbursement.Text = incomeReimbursement.ToString(Resources.DollarFormat);

            labelAllowance.Text = "Allowance (" + days.ToString() + " days): ";
            textBoxAllowance.Text = incomeDailyAllowance.ToString(Resources.DollarFormat);
            textBoxPersonalExpense.Text = ((float)(expenditures + incomeReimbursement)).ToString(Resources.DollarFormat);
            textBoxTotal.Text = total.ToString(Resources.DollarFormat);
            textBoxTotalRupees.Text = ((float)(total * budgetFile.ExchangeRate)).ToString(Resources.RupeeFormat);
        }

        private void PopulateList()
        {
            dataBindingSource.Clear();

            foreach (Data dataItem in budgetFile.DataCollection)
            {
                dataBindingSource.Add(dataItem);
            }

            isDirty = false;
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            if (isDirty && MessageBox.Show("Do you want to save the changes?", "Budgetor", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                budgetFile.DataCollection.Clear();

                foreach (object dataItem in dataBindingSource)
                {
                    budgetFile.DataCollection.Add(dataItem as Data);
                }

                budgetFile.Save();
            }
            base.OnFormClosing(e);
        }

        private void OnRowRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
        {
            budgetFile.DataCollection.RemoveRange(e.RowIndex, e.RowCount);
            CalculateAmount();
        }

        private void OnDataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            DataGridView dataGrid = sender as DataGridView;

            switch (e.ColumnIndex)
            {
                case 0:
                    dataGrid.Rows[e.RowIndex].Cells[0].Value = DateTime.Today;
                    break;
                case 2:
                    dataGrid.Rows[e.RowIndex].Cells[2].Value = 0;
                    break;
                case 3:
                    dataGrid.Rows[e.RowIndex].Cells[3].Value = 0;
                    break;
                default:
                    break;
            }

            e.ThrowException = false;
        }

        private void OnCellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            DataGridView dataGrid = sender as DataGridView;

            if (e.ColumnIndex == 0)
            {
                Object value = dataGrid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
                if (value != null)
                {
                    DateTime dateTime = (DateTime)value;
                    e.Value = dateTime.ToString("dd MMM yy");
                }
            }
            else if (e.ColumnIndex == 2 || e.ColumnIndex == 3)
            {
                Object value = dataGrid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
                if (value != null)
                {
                    float amount = (float)value;
                    e.Value = amount.ToString(Resources.DollarFormat);
                }
            }
        }

        bool isDirty;

        private void OnListChanged(object sender, ListChangedEventArgs e)
        {
            isDirty = true;
        }

        private void OnEditingControlShowingForDataGridView(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            if (e.Control is DataGridViewTextBoxEditingControl)
            {
                DataGridViewTextBoxEditingControl te = (DataGridViewTextBoxEditingControl)e.Control;
                te.AutoCompleteMode = AutoCompleteMode.Append;
                te.AutoCompleteSource = AutoCompleteSource.CustomSource;
                te.AutoCompleteCustomSource.Clear();

                switch (((DataGridView)sender).CurrentCell.ColumnIndex)
                {
                    case 1: te.AutoCompleteCustomSource.AddRange(GetDescriptionList());
                        break;
                    case 5: te.AutoCompleteCustomSource.AddRange(GetCategoryList());
                        break;
                    default:
                        break;
                }

            }
        }

        private string[] GetCategoryList()
        {
            List<string> categoryList = new List<string>();

            foreach (object obj in dataBindingSource)
            {
                Data dataItem = obj as Data;

                if (categoryList.Contains(dataItem.Category) == false && dataItem.Category != null)
                    categoryList.Add(dataItem.Category);
            }

            return categoryList.ToArray();
        }

        private string[] GetDescriptionList()
        {
            List<string> descriptionList = new List<string>();

            foreach (object obj in dataBindingSource)
            {
                Data dataItem = obj as Data;
                
                if (descriptionList.Contains(dataItem.Description) == false && dataItem.Description != null)
                    descriptionList.Add(dataItem.Description);
            }

            return descriptionList.ToArray();
        }

        private void OnCellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex < 0)
                return;

            DataGridView view = sender as DataGridView;
            DataGridViewRow thisRow = view.Rows[e.RowIndex];

            if (e.ColumnIndex == 1 && thisRow.Cells[4].Value == null)
            {
                // New entry, populate with default values
                if ((DateTime)thisRow.Cells[0].Value == new DateTime())
                    thisRow.Cells[0].Value = DateTime.Today;

                // Get the last entry with this description
                int length = dataBindingSource.Count;
                for (int i = length - 2; i >= 0; i--)
                {
                    Data dataItem = dataBindingSource[i] as Data;

                    if (dataItem.Description == (string)thisRow.Cells[1].Value)
                    {
                        thisRow.Cells[2].Value = dataItem.AmountSpent;
                        thisRow.Cells[3].Value = dataItem.AmountReimbursed;
                        thisRow.Cells[4].Value = dataItem.CurrencyMode;
                        thisRow.Cells[5].Value = dataItem.Category;
                        CalculateAmount();
                        break;
                    }
                }
            }

            if (e.ColumnIndex == 2 && e.RowIndex > 0)
                thisRow.Cells[3].Value = thisRow.Cells[2].Value;

            if ((e.ColumnIndex == 2 || e.ColumnIndex == 3) && thisRow.Cells[4].Value != null && thisRow.Cells[5].Value != null)
                CalculateAmount();
        }

        private void OnRowAdded(object sender, DataGridViewRowsAddedEventArgs e)
        {
            DataGridView view = sender as DataGridView;
            //if (view.CurrentRow != null)
            //{
            //    view.CurrentRow.Cells[0].Value = DateTime.Today;
            //    view.CurrentRow.Cells[4].Value = Resources.Cash;
            //}
        }

        private void OnNewFile(object sender, EventArgs e)
        {
            if (isDirty == true && 
                MessageBox.Show("Do you want to save the current file?", "Budgetor", 
                MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes)
            {
                budgetFile.Save();
            }

            budgetFile = new BudgetFile();
            ResetViews();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void OnShowSettings(object sender, EventArgs e)
        {
            SettingsForm settingsForm = new SettingsForm();
            settingsForm.FromDate = budgetFile.AllowanceFrom;
            settingsForm.ToDate = budgetFile.AllowanceTo;
            settingsForm.Amount = budgetFile.DailyAllowance;
            settingsForm.UseCurrentDate = budgetFile.UseCurrentDateForAllowance;
            settingsForm.ExchangeRate = budgetFile.ExchangeRate;

            if (settingsForm.ShowDialog(this) == DialogResult.OK)
            {
                budgetFile.AllowanceFrom = settingsForm.FromDate;
                budgetFile.AllowanceTo = settingsForm.ToDate;
                budgetFile.DailyAllowance = settingsForm.Amount;
                budgetFile.UseCurrentDateForAllowance = settingsForm.UseCurrentDate;
                budgetFile.ExchangeRate = settingsForm.ExchangeRate;

                this.isDirty = true;
                CalculateIncome();
            }
        }

        private void OnSaveFile(object sender, EventArgs e)
        {
            //Dictionary<string, float> report = new Dictionary<string, float>();
            //foreach (object obj in dataBindingSource)
            //{
            //    Data dataItem = obj as Data;
            //    if (dataItem.Category == "Advance")
            //        continue;

            //    float expense = dataItem.AmountReimbursed == 0 ? dataItem.AmountSpent : dataItem.AmountReimbursed;

            //    if (report.ContainsKey(dataItem.Category))
            //        report[dataItem.Category] += expense;
            //    else
            //        report.Add(dataItem.Category, expense);
            //}

            //StreamWriter reportFile = new StreamWriter(@"C:\ExpenseReport.txt");
            //reportFile.WriteLine("Expense details from:");

            //float total = 0;
            //foreach (KeyValuePair<string, float> kvp in report)
            //{
            //    reportFile.WriteLine(String.Format("{0:-15}: {1:0.00}", kvp.Key, kvp.Value));
            //    total += kvp.Value;
            //}

            //reportFile.WriteLine("-----------------------------------------------------");
            //reportFile.WriteLine(String.Format("{0:-15}: {1:0.00}", "Total", total));

            //reportFile.Close();
            budgetFile.Save();
        }

        private void MainForm_Load(object sender, EventArgs e)
        { 
            //List<Data> dataCollection = new List<Data>();

            //histogramdata.Clear();
            //foreach (object data in dataBindingSource)
            //{
            //    Data dataItem = data as Data;
            //    if (dataItem.Category != "Advance")
            //    {
            //        pcc.AddData(dataItem.Description, dataItem.AmountSpent);
            //        histogramdata.Add((double)dataItem.AmountSpent);
            //    }

            //    dataCollection.Add(dataItem);
            //}
           
            
            //histogram.BinCount = 25;
            //histogram.Border = 10;
            //histogram.Data = histogramdata;
            //histogram.XText = "Amount Spent ( in $)";
            //histogram.YText = "Interval";            
            //tabControl.TabPages[2].Controls.Add(histogram);
            ////pieChartPanel1.UpdateChart(dataCollection.ToArray());
            //barGraphPanel1.UpdateData(this, new DataEventArgs(dataBindingSource));
            isDirty = false;
        }

        private void OnSelectionChanged(object sender, EventArgs e)
        {
            DataGridView view = sender as DataGridView;

            if (view.SelectedCells.Count > 0)
            {
                float cashRemaining = 0;

                int rowIndex = view.SelectedCells[0].RowIndex;

                groupBoxAmountRemainingSD.Text = "Amount Remaining on " +
                    ((Data)dataBindingSource[rowIndex]).ToString();

                Data dataItem = null;
                for (int i = 0; i <= rowIndex; i++)
                {
                    dataItem = dataBindingSource[i] as Data;
                    if (dataItem.CurrencyMode == Resources.Cash)
                    {
                        if (dataItem.Category == "Advance")
                            cashRemaining += dataItem.AmountReimbursed;

                        cashRemaining -= dataItem.AmountSpent;
                    }
                }

                textBoxCashRemainingSD.Text = cashRemaining.ToString(Resources.DollarFormat);
            }
        }

        private void OnOpenFile(object sender, EventArgs e)
        {
            OpenFileDialog fileDialog = new OpenFileDialog();
            fileDialog.Filter = "Budget files (*.bdf)|*.bdf";

            if (fileDialog.ShowDialog(this) == DialogResult.OK)
            {
                budgetFile = BudgetFile.Load(fileDialog.FileName);
                ResetViews();
            }
        }

        private void ResetViews()
        {
            PopulateList();
            CalculateAmount();


        }

        private void OnSaveAsFile(object sender, EventArgs e)
        {
            budgetFile.SaveAs();
        }

        private void OnGenerateRequiredRecieptReport(object sender, EventArgs e)
        {
            IReport report = new RequiredReciepts();

            List<Data> dataList = new List<Data>();

            foreach (object data in dataBindingSource)
            {
                dataList.Add(data as Data);
            }

            report.Generate(dataList.ToArray());
        }

        private void OnAbout(object sender, EventArgs e)
        {

        }
    }
}